<?php
	namespace ampleharvest\code\search;
	use\ampleharvest\code\cConfig;

	require_once dirname(dirname(dirname(__FILE__))) . '/config/cConfig.php';
	$codeConfig = new \ampleharvest\code\cConfig();
	
	require_once dirname(dirname(__FILE__)) . "/Tables/cTABLE_Query_History.php";
	require_once dirname(dirname(__FILE__)) . "/classification/cMarkings.php";

	require_once "solr/cDoc.php";
	require_once "solr/cSolr.php";
	require_once dirname(dirname(__FILE__)) . "/cSolrQuery.php";
	/**
	 * @package AmpleHarvest
	 */
	/**
	 * @brief This Class to hold information on createing the AmpleHarvest Database
	 *
	 * - Revision History
	 *  - 0.1
	 * 	 - <b>Date</b>: 20 APR 2011
	 * 	 - <b>Author</b>: Randy Blancett
	 * 	  - Initial Version
	 *
	 * @author Randy Blancett
	 * @version 0.1
	 * @ingroup code
	 */

	class cResults
	{
		protected $m_int_Page = 0;
		protected $m_int_PerPage = 20;
		protected $m_int_Total = 0;
		protected $m_arr_Sort = null;
		protected $m_obj_Solr = null;
		protected $m_obj_Table_QHistory = null;
		protected $m_arr_Query = null;
		protected $m_arr_DisplayFields = null;
		protected $m_obj_Query = null;
		protected $m_str_UserID = "";

		protected $m_arr_SolrParams;

		private $m_obj_Response = null;

		public function __construct()
		{
			ini_set("memory_limit", "100M");
			$this->m_arr_Sort = array(array("Field" => "score", "Direction" => "asc"));
			$this->m_obj_Table_QHistory = new \cTABLE_Query_History();
			$this->m_obj_Query = new \cSolrQuery();
			$this->m_arr_DisplayFields = array("*", "score");
			$this->m_arr_SolrParams = array();
		}

		public function set_SolrParam($str_Key, $str_Value)
		{
			$this->m_arr_SolrParams[$str_Key] = $str_Value;
		}

		public function remove_SolrParam($str_Key)
		{
			if (isset($this->m_arr_SolrParams[$str_Key]))
			{
				unset($this->m_arr_SolrParams[$str_Key]);
			}
		}

		public function clear_Query()
		{
			$this->m_obj_Query = new \cSolrQuery();
		}

		public function set_DisplayFields($arr_Fields)
		{
			$this->m_arr_DisplayFields = $arr_Fields;
		}

		public function process_Query($obj_Condition)
		{
			$str_Key = trim($obj_Condition->property);
			$str_Value = trim($obj_Condition->value);
			$str_Condition = trim($obj_Condition->condition);
			
			$str_Type = "";
			$str_ValueEnd = false;

			if (isset($obj_Condition->value_end))
			{
				$str_ValueEnd = trim($obj_Condition->value_end);
			}
			if (isset($obj_Condition->dataType))
			{
				$str_Type = trim($obj_Condition->dataType);
			}

			switch ($str_Key)
			{
				case 'general':
					if (empty($str_Value) || $str_Value == "")
					{
						break;
					}
					$this->m_obj_Query->add_Query($str_Value,"",$str_Condition);
					break;

				case 'read':

					if (empty($str_Value) || $str_Value == "")
					{
						break;
					}
					$str_Key = \cDoc::C_STR_FIELD_VIEWED;

				default:
					if ($str_ValueEnd)
					{
						switch ($str_Type)
						{
							case "date":

								$obj_StartDate = null;
								if (!(empty($str_Value) || $str_Value == "" || $str_Value == "*"))
								{
									$obj_StartDate = self::convert_Date($str_Value);

									if (!$obj_StartDate)
									{
										print("The Publish Start Date you entered is invalid and will be ignored.<br/>");
										break;
									}
								}

								$obj_EndDate = null;

								if (isset($str_ValueEnd) && ($str_ValueEnd != "*"))
								{
									$obj_EndDate = self::convert_Date(trim($obj_Condition->value_end));
									if (!$obj_EndDate)
									{
										print("The Publish End Date you entered is invalid and will be ignored.<br/>");
										break;
									}

									$obj_EndDate->setTime(23, 59, 59);
								}
								$this->m_obj_Query->add_Query_Date($str_Key, $obj_StartDate, $obj_EndDate);
								break;
							case "value":
								$this->m_obj_Query->add_Query_Range($str_Value, $str_ValueEnd, $str_Key);
								break;
							default:
								$obj_StartDate = null;
								if (!(empty($str_Value) || $str_Value == "" || $str_Value == "*"))
								{
									$obj_StartDate = self::convert_Date($str_Value);

									if (!$obj_StartDate)
									{
										print("The Publish Start Date you entered is invalid and will be ignored.<br/>");
										break;
									}
								}

								$obj_EndDate = null;

								if (isset($str_ValueEnd) && ($str_ValueEnd != "*"))
								{
									$obj_EndDate = self::convert_Date(trim($obj_Condition->value_end));
									if (!$obj_EndDate)
									{
										print("The Publish End Date you entered is invalid and will be ignored.<br/>");
										break;
									}

									$obj_EndDate->setTime(23, 59, 59);
								}
								$this->m_obj_Query->add_Query_Date($str_Key, $obj_StartDate, $obj_EndDate);
								break;

						}
					}
					elseif (empty($str_Value) || $str_Value == "")
					{
						break;
					}
					else
					{
						$this->m_obj_Query->add_Query($str_Value, $str_Key,$str_Condition);
					}
					break;
			}
		}

		public function add_Query($str_Key, $str_Value,$str_Condition=\cSolrQuery::C_STR_QUERY_CONDITION_EQUALS, $str_Join = \cSolrQuery::C_STR_QUERY_JOIN_AND)
		{
			$this->m_obj_Query->add_Query($str_Value, $str_Key,$str_Condition, $str_Join);
		}

		public function add_Query_Range($obj_Start, $obj_End = null, $str_Field = \cSolrQuery::C_STR_QUERY_DEFAULT, $str_Join = \cSolrQuery::C_STR_QUERY_JOIN_AND)
		{
			$this->m_obj_Query->add_Query_Range($obj_Start, $obj_End, $str_Field, $str_Join);
		}

		public function isActive()
		{
			return $this->m_obj_Query->isActive();
		}

		public static function convert_Date($str_Date)
		{
			$obj_Date = null;
			try
			{
				$obj_Date = new \DateTime($str_Date);
			}
			catch (Exception $e)
			{
			}
			return $obj_Date;
		}

		protected function process_QueryArray($arr_Query)
		{
			foreach ($arr_Query as $obj_Data)
			{
				switch (strtolower($obj_Data->type))
				{
					case "condition":
						if (isset($obj_Data->value))
						{
							$this->process_Query($obj_Data);
						}
						break;
					case "group":
						if (isset($obj_Data->children))
						{
							$this->m_obj_Query->start_Group();
							$this->process_QueryArray($obj_Data->children);
							$this->m_obj_Query->end_Group();
						}
						break;
					default:
						print("Unknown Type (cResults line " . __LINE__ . " - " . $obj_Data->type . "<br/>\n");

				}
			}
		}
		/**
		 * Sets the query takes a String that represents a json object
		 * @param string $str_Query the query (json object)
		 */
		public function set_QueryFromJson($str_Json)
		{
			if (is_string($str_Json))
			{
				//$str_Json = str_ireplace("\\\"", "\"", $str_Json);
				$str_Json = str_ireplace("\\\\\"", "\\\"", $str_Json);
				$str_Json = str_ireplace("\\\\", "\\", $str_Json);

				$arr_Query = json_decode($str_Json);
			}
			else
			{
				$arr_Query = $str_Json;
			}

			//print_r($arr_Query);

			if (!isset($arr_Query->Query))
			{
				return false;
			}

			if (sizeof($arr_Query->Query) < 1)
			{
				return false;
			}

			if (isset($arr_Query->Query))
			{
				$this->process_QueryArray($arr_Query->Query);
			}

			if (isset($arr_Query->Sort))
			{
				foreach ($arr_Query->Sort as $obj_Data)
				{
					if (isset($obj_Data->Field))
					{
						$str_Field = trim($obj_Data->Field);
						$str_Direction = "desc";
						if ($str_Field != "")
						{
							if (isset($obj_Data->Direction))
							{
								if (trim($obj_Data->Direction) != "")
								{
									$str_Direction = $obj_Data->Direction;
								}
							}
							$this->m_arr_Sort[0] = array("Field" => $str_Field, "Direction" => $str_Direction);
						}
					}
				}
			}
			return true;
		}

		public function set_Solr($obj_Solr)
		{
			$this->m_obj_Solr = $obj_Solr;
		}

		public function set_UserID($str_UserID)
		{
			$this->m_str_UserID = $str_UserID;
		}

		public function set_Page($int_Page)
		{
			$this->m_int_Page = $int_Page;
		}

		public function set_PerPage($int_PerPage)
		{
			$this->m_int_PerPage = $int_PerPage;
		}

		public function get_Page()
		{
			return $this->m_int_Page;
		}

		public function get_Query()
		{
			return (string) $this->m_obj_Query;
		}

		public function get_Total()
		{
			return $this->m_int_Total;
		}

		public function get_PerPage()
		{
			return $this->m_int_PerPage;
		}

		private function query_Solr()
		{
			$this->set_SolrParam(\cSolr::C_STR_PARAM_RETURN_FIELDS, implode(",", $this->m_arr_DisplayFields));
			$this->set_SolrParam(\cSolr::C_STR_PARAM_RETURN_SORT, $this->m_arr_Sort[0]["Field"] . " " . $this->m_arr_Sort[0]["Direction"]);
			$this->set_SolrParam(\cSolr::C_STR_PARAM_HIGHLIGHT, "true");
			$this->set_SolrParam(\cSolr::C_STR_PARAM_HIGHLIGHT_REQUIRE_MATCH, "true");
			$this->set_SolrParam(\cSolr::C_STR_PARAM_HIGHLIGHT_FIELDS, "*");
			try
			{
				$this->m_obj_Response = $this->m_obj_Solr->search((string) $this->m_obj_Query,
					($this->get_Page() * $this->get_PerPage()),
					$this->get_PerPage(),
					$this->m_arr_SolrParams);
			}
			catch (Exception $e)
			{
				print("There has been an error Executeing your Query <br/>");
				print($e->getMessage());
				return false;
			}

			$this->m_obj_Table_QHistory->set_user_id($this->m_str_UserID);
			$this->m_obj_Table_QHistory->set_query((string) $this->m_obj_Query);
			$this->m_obj_Table_QHistory->save_Data2DB();
		}

		public function output_ResultsAsHTML()
		{
			$obj_Markings = new \cMarkings(\cMarkings::C_STR_UNCLASSIFIED);
			$str_Output = <<<EOM
			<html>
				<head>
					<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
					<style>
						label
						{
							font-weight		: bold;
						}
					</style>
				</head>
				<body>
EOM;
			print($str_Output);
			
				print($obj_Markings->get_OverallEmailBanner());
			
			print "Query - " . $this->m_obj_Query . " <br />";

			if ($this->m_obj_Query->isActive())
			{
				$this->query_Solr();

				if ($this->m_obj_Response->getHttpStatus() == 200)
				{

					$this->m_int_Total = $this->m_obj_Response->response->numFound;
					print "Results - " . $this->m_int_Total . " <hr />";

					//print_r( $this->m_obj_Response->getRawResponse() );
					//die();

					if ($this->m_int_Total > 0)
					{
						foreach ($this->m_obj_Response->response->docs as $id => $doc)
						{
							$int_ID = $doc->id;
							//$obj_Highlight = $this->m_obj_Response->highlighting->$id;
							//$obj_Doc = $this->create_Doc($doc, $this->m_obj_Response->highlighting->$int_ID);
							//$obj_Doc = new cDocTemplate($doc);
							$this->output_HTML($doc);
							//$obj_Doc->output_HTML();
						}

						echo '<br />';
					}
					else
					{
						print("No Results Found.");
					}
				}
				else
				{
					echo $this->m_obj_Response->getHttpStatusMessage();
				}
			}
			else
			{
				print("You must Search for something.");
			}
			
				print("\n".$obj_Markings->get_OverallEmailBanner());
			print("</body></html>");
			return true;
		}

		public function output_ResultsAsArray()
		{
			$arr_Output = array();
			$arr_Output["query"] = (string) $this->m_obj_Query ;
			
			//print($arr_Output["query"]);

			if ($this->m_obj_Query->isActive())
			{
				$this->query_Solr();

				if ($this->m_obj_Response->getHttpStatus() == 200)
				{

					//print_r( $this->m_obj_Response->getRawResponse() );
					//die();

					$this->m_int_Total = $this->m_obj_Response->response->numFound;

					$arr_Output["total"] = $this->m_int_Total ;
					$arr_Output["qtime"] = $this->m_obj_Response->responseHeader->QTime ;
					
					if(isset($this->m_obj_Response->facet_counts))
					{
						$arr_Output["facet"] = $this->m_obj_Response->facet_counts;
					}
					
					if ($this->m_int_Total > 0)
					{
						//print_r($this->m_obj_Response->response->docs);{
						//print_r($this->m_obj_Response->highlighting);
						//$arr_Output["docs"]= $this->m_obj_Response->response->docs;

						foreach ($this->m_obj_Response->response->docs as $id => $doc)
						{
							$int_ID = $doc->id;
							$obj_Temp = new \stdClass();

							foreach ($doc as $key => $value)
							{
								switch ($key)
								{
									case "content":
										$obj_Temp->$key = substr(strip_tags($value), 0, 200);
										break;
									default:
										$obj_Temp->$key = $value;
								}
							}
							if(isset($this->m_obj_Response->highlighting->$int_ID))
							{
								foreach ($this->m_obj_Response->highlighting->$int_ID as $str_Key => $arr_Highlight)
								{
									$obj_Temp->highlight[$str_Key] = $arr_Highlight;
								}
							}
							//$obj_Temp->highlight = $this->m_obj_Response->highlighting;

							$arr_Output["docs"][] = $obj_Temp;
						}

					}
				}
				else
				{
					echo $this->m_obj_Response->getHttpStatusMessage();
				}
			}
			else
			{
				return false;
			}
			return $arr_Output;
		}

		private function output_HTML($obj_Data)
		{
			$str_Output = <<<EOM
				<div style="border-style:solid;border-width:1px;margin:2px;">
					<div style="width:100%;background-color:gray;padding:2px;">
						{$obj_Data->__get(\cDoc::C_STR_FIELD_TITLE)}
					</div>
					<div style="padding:2px;">
						<div class="summary">
EOM;
			$str_Output .= strip_tags($obj_Data->__get(\cDoc::C_STR_FIELD_SUMMARY));
			
			$str_Output .= <<<EOM
						</div>
						<div class="highlight">
EOM;
	
		if (isset($this->highlighting))
			{
				foreach ($this->highlighting as $str_Key => $arr_Data)
				{
					$str_Output .= <<<EOM
						<span class="label">
						$str_Key :
						</span>
						<span class="data">
EOM;
					for ($int_I = 0; $int_I < sizeof($arr_Data); $int_I++)
					{
						$str_Output .= strip_tags($arr_Data[$int_I], "<em></em>") . "<br/>";
					}
						
					$str_Output .= <<<EOM
						</span>
EOM;
				}
			}
			$str_PublishDate= new \DateTime($obj_Data->__get(\cDoc::C_STR_FIELD_PUBLISH_DATE));
			if ($str_PublishDate->format("Y") > 100)
			{
				$str_PublishDate = $str_PublishDate->format("Y/m/d H:i:s");
			}
			else
			{
				$str_PublishDate="Unknown";
			}
			
			$str_HarvestDate= new \DateTime($obj_Data->__get(\cDoc::C_STR_FIELD_HARVEST_DATE));
			if ($str_HarvestDate->format("Y") > 100)
			{
				$str_HarvestDate = $str_HarvestDate->format("Y/m/d H:i:s");
			}
			else
			{
				$str_HarvestDate="Unknown";
			}
			
			$str_IndexDate= new \DateTime($obj_Data->__get(\cDoc::C_STR_FIELD_INDEX_DATE));
			if ($str_IndexDate->format("Y") > 100)
			{
				$str_IndexDate = $str_IndexDate->format("Y/m/d H:i:s");
			}
			else
			{
				$str_IndexDate="Unknown";
			}
			$str_URL = $codeConfig->C_STR_WEB_PATH."/pages/article/index.php?id=".$obj_Data->__get(\cDoc::C_STR_FIELD_ID);
			$str_Output .= <<<EOM
						</div>
						<div style="padding:2px;">
							<span style="font-weight: bold;">Source :</span> <span >{$obj_Data->__get(\cDoc::C_STR_FIELD_SOURCE)}</span>
						</div>
						<div style="padding:2px;">
							<span style="font-weight: bold;">Publish Date : </span> <span >$str_PublishDate</span>
						</div>
						<div style="padding:2px;">
							<span style="font-weight: bold;">Harvest Date : </span> <span >$str_HarvestDate</span>
						</div>
						<div style="padding:2px;">
							<span style="font-weight: bold;">Index Date : </span> <span >$str_IndexDate</span>
						</div>
						<div style="padding:2px;">
							<span style="font-weight: bold;">Score : </span> <span >{$obj_Data->__get(\cDoc::C_STR_FIELD_SCORE)}</span>
						</div>
						<div style="padding:2px;">
							<span style="font-weight: bold;">View : </span> <span >
								<a target="_blank" href="$str_URL">
									{$obj_Data->__get(\cDoc::C_STR_FIELD_TITLE)}
								</a>
							</span>
						</div>
					</div>
				</div>
EOM;
			print($str_Output);
		}
	}
?>
